home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / rexx / imc / rexx-imc.5 / rxstack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-25  |  5.9 KB  |  144 lines

  1. /* Utility to access the REXX/imc stack server     (C) Ian Collier 1992 */
  2.  
  3. #include<sys/types.h>
  4. #include<sys/socket.h>
  5. #include<stdio.h>
  6. #include<string.h>
  7. #include<stdlib.h>
  8. #include<malloc.h>
  9. #include<signal.h>
  10.  
  11. void ex1t();
  12.  
  13. struct {u_short af;char name[100];}  /* a mimic of struct sockaddr, but */
  14.        sock={AF_UNIX};               /* with a longer name field. */
  15. int socklen;                         /* The length of the socket name */
  16. char *buff;                          /* An input buffer */
  17. unsigned bufflen;                    /* The amount of memory allocated */
  18. int s;                               /* The socket fd */
  19.  
  20. main(argc,argv)
  21. int argc;
  22. char **argv;
  23. {
  24.    int fifo=1;                       /* fifo or lifo */
  25.    int c;
  26.    static char *opts[]={"-fifo","-lifo","-string","-pop","-peek","-drop",
  27.                         "-num","-print"};  /* All the allowed options */
  28.    static int optnum=8;              /* The number of allowed options */
  29.    int opt=0;                        /* position of an option in the above */
  30.    char id;                          /* a command character */
  31.    char *string;                     /* The parameter of -string flag */
  32.    int len;
  33.    static char out[10];              /* A buffer for sprintf */
  34.    char *env=getenv("RXSTACK");      /* The socket's file name */
  35.    if(!env)fputs("RX Stack not found\n",stderr),exit(1);
  36.    if(!(buff=malloc(bufflen=256)))perror("Unable to allocate memory"),exit(1);
  37.    strcpy(sock.name,env);
  38.    socklen=sizeof(u_short)+strlen(env);
  39.    for(c=1;c<argc;c++){              /* Find first "action" flag */
  40.       for(opt=0;opt<optnum&&strcmp(opts[opt],argv[c]);opt++);
  41.       if(opt==optnum)fprintf(stderr,"Invalid option: %s\n",argv[c]),exit(1);
  42.       if(opt>1)break;
  43.       if(opt==0)fifo=1;else fifo=0;  /* Deal with -fifo and -lifo and go on */
  44.    }
  45.    if(argc>++c+(opt==2))fputs("Too many options\n",stderr),exit(1);
  46.    if(opt<2)opt=0;                   /* no "action"; stack from stdin */
  47.    s=socket(AF_UNIX,SOCK_STREAM,0);  /* Try to connect... */
  48.    if(s<0)perror("Error in socket call"),exit(1);
  49.    if(connect(s,&sock,socklen)<0)perror("Error in connect call"),exit(1);
  50.    id=fifo?'Q':'S';                  /* Queue if fifo, Stack if lifo. */
  51.    switch(opt){                      /* Select the appropriate action */
  52.       case 0:while(1){               /* Default: collect lines from stdin */
  53.                 len=0;
  54.                 while((c=getchar())!=EOF&&c!='\n'){
  55.                    if(len>=bufflen&&!(buff=realloc(buff,bufflen<<=1)))
  56.                       perror("Out of memory"),exit(1);
  57.                    buff[len++]=c;
  58.                 }
  59.                 if(c==EOF&&!len)break;
  60.                 sprintf(out,"%c%06X\n",id,len);
  61.                 if(write(s,out,8)<8||write(s,buff,len)<len)
  62.                    perror("Error writing data"),exit(1);
  63.              }
  64.              break;
  65.       case 2:string=(c>=argc?"":argv[c]);/* Stack argument following -string */
  66.              sprintf(out,"%c%06X\n",id,len=strlen(string)); 
  67.              if(write(s,out,8)<8||write(s,string,len)<len)
  68.                 perror("Error writing data"),exit(1);
  69.              break;
  70.       case 3:pop('G',1);break;       /* -pop: use the "Get" command */
  71.       case 4:pop('P',1);break;       /* -peek: use the "Peek" command */
  72.       case 5:if(write(s,"D",1)<1)    /* -drop: write a "Drop" command */
  73.                 perror("Error writing data"),exit(1);
  74.              break;
  75.       case 6:if(write(s,"N",1)<1)    /* -num: write a "Num" command; get ans */
  76.                 perror("Error reading data"),exit(1);
  77.              if(read(s,buff,7)<7)perror("Error reading data"),exit(1);
  78.              len=x2d(buff);
  79.              printf("%d\n",len);
  80.              fflush(stdout);
  81.              break;
  82.       case 7:while(pop('P',0)!=0xffffff) /* -print: continually peek, then */
  83.                 if(write(s,"D",1)<1)     /* drop.                          */
  84.            perror("Error writing data"),exit(1);
  85.    }               /* This way, if the output is being read by a program which
  86.                       terminates, a SIGPIPE arrives and any unread data is
  87.               still on the stack. */
  88.    if(opt<3||opt==5){ /* wait for the stack process to catch up */
  89.       signal(15,ex1t); /* kludge to make a zero return code */
  90.       sprintf(out,"K%06X\n\017",getpid()); /* kill me with SIGTERM */
  91.       if(write(s,out,9)<9)perror("Error writing data"),exit(1);
  92.       pause();
  93.    }
  94.    close(s);
  95.    return 0;
  96. }
  97.  
  98. void ex1t() {close(s);exit(0);} /* on SIGTERM, just exit with return code 0 */
  99.  
  100. int x2d(hex)       /* Convert six hex digits from "hex" into an integer */
  101. char *hex;
  102. {
  103.    int i,len=0;
  104.    char c;
  105.    for(i=0;i<6;i++){
  106.       len<<=4;
  107.       if((c=hex[i])>='0'&&c<='9')len+=c-'0';
  108.       else if(c>='A'&&c<='F')len+=c-'A'+10;
  109.       else if(c>='a'&&c<='f')len+=c-'a'+10;
  110.    }
  111.    return len;
  112. }
  113.  
  114. int pop(id,nullok)  /* Print the top value from the stack, using "id" as */
  115. char id;            /* the command character.  If the stack is empty and */
  116. int nullok;         /* nullok!=0 then print a newline, else just return. */
  117. {                   /* The return value is the length given by the stack */
  118.    int len;
  119.    int rdlen;
  120.    int i;
  121.    if(write(s,&id,1)<1)    /* write the command character */
  122.       perror("Error writing data"),exit(1);
  123.    if(read(s,buff,7)<7)    /* Expect a length to be returned */
  124.       perror("Error reading data"),exit(1);
  125.    len=x2d(buff);
  126.    if(len!=0xffffff){      /* Stack wasn't empty, so expect some data */
  127.       if(len>bufflen&&!(buff=realloc(buff,(unsigned)len)))
  128.          perror("Out of memory"),exit(1);
  129.       rdlen=0;
  130.       while(rdlen<len)     /* Read the data */
  131.          if((i=read(s,buff+rdlen,len-rdlen))<1)
  132.         perror("Error reading data"),exit(1);
  133.      else rdlen+=i;
  134.       fwrite(buff,1,len,stdout); /* Write the data to stdout */
  135.       putchar('\n');
  136.       fflush(stdout);      /* Make sure the application reads this */
  137.    }
  138.    else if(nullok){        /* Stack was empty; write an empty line */
  139.       putchar('\n');
  140.       fflush(stdout);
  141.    }
  142.    return len;
  143. }
  144.